<template>
  <div v-if="error" class="error-boundary">
    <template v-if="fallback">
      <component :is="fallback(error)" />
    </template>
    <template v-else>
      <div class="error-content">
        <h3 class="error-title">出错了</h3>
        <p class="error-message">{{ error.message }}</p>
        <el-button type="primary" @click="handleReset">重试</el-button>
      </div>
    </template>
  </div>
  <slot v-else />
</template>
<script setup lang="ts">
import { onErrorCaptured, ref } from 'vue'
import type { ErrorBoundaryEvents, ErrorBoundaryOptions } from './types'

const props = withDefaults(defineProps<ErrorBoundaryOptions>(), {
  showError: true,
})

const emit = defineEmits<ErrorBoundaryEvents>()

const error = ref<Error | null>(null)

// 错误捕获
onErrorCaptured((err: Error, instance, info) => {
  error.value = err
  emit('error', err, info)
  if (props.onError) {
    props.onError(err, info)
  }
  return false
})

// 处理重置
const handleReset = () => {
  error.value = null
}
</script>
<style scoped>
.error-boundary {
  padding: 20px;
  text-align: center;
}
.error-content {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
}
.error-title {
  margin: 0;
  font-size: 18px;
  font-weight: 500;
  color: var(--el-text-color-primary);
}
.error-message {
  margin: 0;
  font-size: 14px;
  color: var(--el-text-color-secondary);
}
</style>
